# -*- encoding: utf-8 -*-
"""
PB连接shein数据接口
@ver     :   1.1.1
@File    :   con2shein.py    
@Time    :   2021-02-04 21:30
"""

import requests
import time
from datetime import datetime
from random import choices
from hashlib import sha256
import base64
import hmac
import sys
import os
import win32gui
import win32api
import configparser
from enum import Enum


class Err(Enum):
    InvalidRequestType = 1
    CanNotFindParseRule = 2
    ParseErr = 3
    Success = 4
    CanNotReadConfig = 5
    CanNotSaveResult = 6
    NotEnoughParameters = 7
    RequestsErr = 8
    InvalidUrl = 9


ErrDescription = [
    "Err1:无效请求类型 有效请求类型为GET或POST",
    "Err2:无法加载解析模块，检查接口目录下是否包含：parserulers.data文件",
    "Err3:请求结果解析失败",
    "Err4:获取数据成功",
    "Err5:读取config.ini失败",
    "Err6:保存请求结果失败，请确认config.ini的txtpath路径是否有效",
    "Err7:PB RUN 参数不足",
    "Err8:API请求失败，详细请求请查看c:/err.log",
    "Err9:API地址为空",
]


def SendMsgToErp(type, err: Err):
    pass
    # 发送反馈信息给ERP
    hWndList = []
    win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWndList)
    for hwnd in hWndList:
        title = win32gui.GetWindowText(hwnd)
        if (title.find(windowtitle) >= 0):
            win32api.PostMessage(hwnd, 1600, type, err.value)


"""
调试环境引入解析方法
生产环境，引入失败则读取parserules.data文件
动态加载解析方法
"""
try:
    from sheinparse import *
except BaseException:
    try:
        parser = os.path.join(os.getcwd(), "parserules.data")
        with open(parser, "rb") as f:
            content = f.read()
        scripts = base64.decodebytes(content[5:]).decode("utf-8")
        exec(scripts)
    except BaseException as e:
        SendMsgToErp(0, Err.CanNotFindParseRule)
        print(e)


def GenSignature(url, openKeyId, timeStamp, secretKey):
    # 构造签名

    print("start GenSignature...")
    print("openKeyId:", openKeyId, "-len:", len(openKeyId))
    print("secretKey:", secretKey, "-len:", len(secretKey))

    # 签名因子value
    value = f"{openKeyId}&{timeStamp}&{url}".encode('utf-8')

    # 签名因子key
    refDict = "0123456789"
    refDict += "".join([chr(x) for x in range(65, 91)])
    refDict += "".join([chr(x) for x in range(97, 123)])
    refKey = ''.join(choices(refDict, k=5))
    key = f"{secretKey}{refKey}".encode('utf-8')

    # sha256加密
    encodeBySha256 = hmac.new(
        key, value, digestmod=sha256).hexdigest().encode('utf-8')

    # base64转码
    toBase64 = str(base64.b64encode(encodeBySha256), "utf-8")

    # 拼接签名
    sign = refKey + toBase64

    return sign


def XRequest(url, type, data):
    # 发送请求
    timeStamp = "%s" % int(round(time.time() * 1000))
    sign = GenSignature(url, openKeyId, timeStamp, secretKey)
    headers = {
        "Content-Type": "application/json;charset=UTF-8",
        "x-lt-openKeyId": openKeyId,
        "x-lt-timestamp": timeStamp,
        "x-lt-signature": sign
    }
    res = {}
    apiurl = aHost+url

    # opts:请求参数状态类别
    opts = "Err Report\n"
    opts += f"ApiUrl:{apiurl}\nRequestType:{type}\n"
    opts += "Headers:\n"
    t = ''.join(['   '+x+':'+headers[x]+'\n' for x in headers])
    opts += f"{t}"
    opts += "\nexcept info:\n"
    if type == "GET":
        try:
            res = requests.get(url=apiurl, headers=headers, params=data)
            res = res.json()
        except BaseException as e:
            print("请求异常")
            SendMsgToErp(0, Err.RequestsErr)
            opts += "%s" % e
            with open("c:/err.log", 'w') as f:
                f.write(opts)
            return None
    else:
        try:
            dd = {
                "query": [
                    {
                        "supplier_sku": "",
                        "skc": "rescreen18210203629",
                        "size": "XS Max"
                    }
                ]
            }

            res = requests.post(url=apiurl, headers=headers, data=dd)
            res = res.json()
        except BaseException as e:
            opts += "%s" % e
            with open("c:/err.log", 'w') as f:
                f.write(opts)
            return None

    return {"url": url, "resp": res} 


def SaveData(res):
    # 成功读取数据，保存数据到txt，并通知ERP
    try:
        with open(txtpath, "w") as f:
            f.write(res)
        SendMsgToErp(1, Err.Success)
    except BaseException as e:
        SendMsgToErp(0, Err.CanNotSaveResult)


def ParseRunParms(parms):
    """
    获取程序运行参数==》解析参数==》发送请求
    调用示例

    必填参数：xxurl(api地址) xxtype(请求类型)  
     con2shein.exe xxurl=/open-api/order/purchase-order-infos xxtype=get page=1 per_page=20 type=2

    调试命令： 
    python con2shein.py xxurl=/open-api/order/purchase-order-infos xxtype=get page=1 per_page=20 type=2   


    商品接口-全量查询SKC/SKU/设计款号关系列表：
    https://openapi-portal.sheincorp.cn/#/home/3/5029/1
    python con2shein.py xxurl=/open-api/goods/number-list xxtype=get page=1 per_page=20 type=1


    python con2shein.py xxurl=/open-api/goods/detail xxtype=get design_code=



    python con2shein.py xxurl=/open-api/order/purchase-order-infos xxtype=get pageSize=20 pageNumber=1 type=1

    """
    # 解析参数
    datas = {}
    for parm in parms:
        t = parm.split("=")
        datas[t[0]] = t[1]

    xxurl = datas.pop("xxurl")
    xxtype = datas.pop("xxtype").upper()

    if xxurl == "":
        SendMsgToErp(0, Err.InvalidUrl)
        return
    if xxtype not in ("POST", "GET"):
        SendMsgToErp(0, Err.InvalidRequestType)
        return
    # 发送请求
    res = XRequest(xxurl, xxtype, datas)
    # print(res)
    if res:
        resParse = ParseResult(res["url"], res["resp"])         

    if resParse["code"] == 0:
       print("err")
    else:
        SaveData(resParse["data"])
if __name__ == "__main__":
    # 读取 ini配置文件

    import configparser
    config = configparser.ConfigParser()
    inifile = os.path.join(os.getcwd(), "config.ini")
    config.read(inifile, encoding="utf-8")

    # PB调用的窗口名称 即窗口的title属性
    windowtitle = config.get("erp", "windowtitle")
    try:
        # 接口相关
        aHost = config.get("shein", "aHost")
        openKeyId = config.get("shein", "openKeyId")
        secretKey = config.get("shein", "secretKey")

        # erp相关
        txtpath = config.get("erp", "txtpath")
    except Exception as e:
        SendMsgToErp(0, Err.CanNotReadConfig)
        exit()
    if len(sys.argv) > 1:
        ParseRunParms(sys.argv[1:])
    else:
        SendMsgToErp(0, Err.NotEnoughParameters)
